home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / unix / tracker_4_3.lzh / tracker / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-13  |  15.1 KB  |  573 lines

  1. /* main.c 
  2.     vi:se ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  */
  14.  
  15. /* $Id: main.c,v 4.3 1994/02/04 14:53:03 espie Exp espie $
  16.  * $Log: main.c,v $
  17.  * Revision 4.3  1994/02/04  14:53:03  espie
  18.  * Nice OPT_CUT/OPT_ADD.
  19.  *
  20.  * Revision 4.2  1994/01/13  09:16:00  espie
  21.  * *** empty log message ***
  22.  *
  23.  * Revision 1.10  1994/01/12  16:12:34  espie
  24.  * Last minute changes.
  25.  *
  26.  * Revision 4.1  1994/01/12  16:11:07  espie
  27.  * Last minute changes.
  28.  *
  29.  * Revision 4.0  1994/01/11  17:49:27  espie
  30.  * Base main.c for unix and others.
  31.  *
  32.  * Revision 1.11  1994/01/09  17:36:22  Espie
  33.  * Generalized open.c.
  34.  *
  35.  * Revision 1.10  1994/01/09  04:50:56  Espie
  36.  * ?
  37.  *
  38.  * Revision 1.9  1994/01/08  03:55:43  Espie
  39.  * Slight input/output changes.
  40.  * No more call to create_notes_table().
  41.  *
  42.  * Revision 1.8  1994/01/08  02:04:21  Espie
  43.  * Some notice to status.
  44.  *
  45.  * Revision 1.7  1994/01/06  22:32:42  Espie
  46.  * Use new pref scheme.
  47.  *
  48.  * Revision 1.6  1994/01/05  16:10:49  Espie
  49.  * *** empty log message ***
  50.  *
  51.  * Revision 1.5  1994/01/05  14:54:09  Espie
  52.  * *** empty log message ***
  53.  *
  54.  * Revision 1.4  1994/01/05  13:50:43  Espie
  55.  * Cosmetic change.
  56.  *
  57.  * Revision 1.3  1993/12/28  13:54:44  Espie
  58.  * Use info facility instead of printf for usage message.
  59.  *
  60.  * Revision 1.2  1993/12/26  18:54:21  Espie
  61.  * Modified in a more consistent way.
  62.  *
  63.  * Revision 1.1  1993/12/26  00:55:53  Espie
  64.  * Initial revision
  65.  *
  66.  * Revision 3.20  1993/12/04  17:15:18  espie
  67.  * New version.
  68.  *
  69.  * Revision 3.19  1993/12/04  16:12:50  espie
  70.  * Options changes.
  71.  *
  72.  * Revision 3.18  1993/12/02  15:45:33  espie
  73.  * Changed extended file semantics.
  74.  *
  75.  * Revision 3.17  1993/11/17  15:31:16  espie
  76.  * New version.
  77.  *
  78.  * Revision 3.16  1993/11/11  20:00:03  espie
  79.  * Amiga support.
  80.  *
  81.  * Revision 3.15  1993/08/04  11:55:21  espie
  82.  * Fixed upo previous song bug.
  83.  *
  84.  * Revision 3.13  1993/07/18  10:39:44  espie
  85.  * Added forking under unix. Experimental...
  86.  *
  87.  * Revision 3.11  1993/05/09  14:06:03  espie
  88.  * Fixed up bug with mix option no longer working.
  89.  *
  90.  * Revision 3.10  1993/04/25  15:13:36  espie
  91.  * Force new version.
  92.  *
  93.  * Revision 3.9  1993/01/15  14:00:28  espie
  94.  * Added bg/fg test.
  95.  *
  96.  * Revision 3.7  1992/12/03  15:00:50  espie
  97.  * restore stty.
  98.  *
  99.  * Revision 3.5  1992/11/24  10:51:19  espie
  100.  * Added loads of new options.
  101.  *
  102.  * Revision 3.3  1992/11/22  17:20:01  espie
  103.  * Augmented usage.
  104.  *
  105.  * Revision 3.2  1992/11/20  14:53:32  espie
  106.  * Added finetune.
  107.  *
  108.  * Revision 3.1  1992/11/19  20:44:47  espie
  109.  * Protracker commands.
  110.  *
  111.  * Revision 3.0  1992/11/18  16:08:05  espie
  112.  * New release.
  113.  *
  114.  * Revision 2.20  1992/11/17  17:06:25  espie
  115.  * Added PREVIOUS_SONG handling ???
  116.  * Use streamio for new interface (obsolescent signal handlers), and
  117.  * related changes.
  118.  * Cleaned up path reader, and better signal handling.
  119.  * Support for open_file.
  120.  * Added imask.
  121.  * Use transparent decompression/path lookup through open_file/close_file.
  122.  * Added setup_audio().
  123.  * Added some frequency/oversample/stereo change on the fly.
  124.  * Necessitates rightful closing/reopening of audio.
  125.  * Added compression methods. Changed getopt.
  126.  * Separated mix/stereo stuff.
  127.  * Added transpose feature.
  128.  * Added possibility to get back to MONO for the sgi.
  129.  * Added stereo capabilities to the indigo version.
  130.  * Added recovery and reread for automatic recognition
  131.  * of old/new tracker files.
  132.  * Added two level of fault tolerancy.
  133.  * Added more rational options.
  134.  * Moved almost everything to audio and automaton.
  135.  * Structured part of the code, especially replay ``automaton''
  136.  * and setting up of effects.
  137.  *
  138.  * Revision 1.26  1991/11/17  17:09:53  espie
  139.  * Added missing prototypes.
  140.  * Some more info while loading files.
  141.  * Added FAULT env variable, FAULT resistant playing,
  142.  * for playing modules which are not quite correct.
  143.  * Serious bug: dochangespeed was not reset all the time.
  144.  * Check all these parameters, they MUST be reset for
  145.  * each new song.
  146.  * Fixed a stupid bug: when env variable LOOPING was
  147.  * undefined, we got a segv on strcmp.
  148.  * Now we just test for its existence, since this is
  149.  * about all we want...
  150.  * Bug correction: when doing arpeggio, there might not
  151.  * be a new note, so we have to save the old note value
  152.  * and do the arppeggio on that note.
  153.  * Completely added control with OVERSAMPLE and FREQUENCY.
  154.  * Added control flow.
  155.  * Added pipe decompression, so that now you can do
  156.  * str32 file.Z directly.
  157.  * stdin may go away.
  158.  * Added arpeggio.
  159.  * Added vibslide and portaslide.
  160.  * Added speed command.
  161.  * Added signal control.
  162.  * Error checking: there shouldn't be that many
  163.  * segv signals any more.
  164.  * Moved every command to commands.c.
  165.  * Added some debug code for showing the full
  166.  * sequence for a file.
  167.  * Corrected the bug in volume slide: there is
  168.  * no default value, i.e., if it is 0, it is 0,
  169.  * as stupid as it may seem.
  170.  * Added vibrato.
  171.  * Added fastskip/corrected skip.
  172.  * Modified control flow of the player till
  173.  * it looks like something reasonable (i.e.,
  174.  * the structure is more natural and reflects
  175.  * the way stuff is played actually...)
  176.  * Do not restart the sound when we change instruments
  177.  * on the fly. A bit strange, but it works that way.
  178.  * Modified main to use new data structures.
  179.  * The sound player is MUCH cleaner, it uses now
  180.  * a 3-state automaton for each voice.
  181.  * Corrected ruckus with data type of sample.
  182.  */
  183.      
  184.  
  185. #include "defs.h"
  186.  
  187. #include <stdio.h>
  188. #include <signal.h>
  189. #include <stdlib.h>
  190. #include <string.h>
  191. #ifdef MALLOC_NOT_IN_STDLIB
  192. #include <malloc.h>
  193. #endif
  194. #include <ctype.h>
  195. #ifdef VOLUME_CONTROL
  196. #ifdef __hpux
  197. #define true /* kludge to avoid typedef of boolean (name clash with macro) */
  198. #include <audio/Alib.h>
  199. #undef true
  200. AGainDB    volume = -20;
  201. char use_speaker = 0;
  202. #endif
  203. #endif
  204.  
  205.      
  206. #include "song.h"
  207. #include "extern.h"
  208. #include "options.h"
  209.  
  210. #include "getopt.h"
  211. #include "tags.h"
  212. #include "prefs.h"
  213.      
  214. ID("$Id: main.c,v 4.3 1994/02/04 14:53:03 espie Exp espie $")
  215.  
  216.  
  217. LOCAL void print_usage()
  218.    {
  219.    GENERIC handle;
  220.    
  221.    handle = begin_info("Usage");
  222.    info(handle, "Usage: tracker [options] filename [...]");
  223.    info(handle, "-help               Display usage information");
  224.    info(handle, "-quiet              Print no output other than errors");
  225.    info(handle, "-picky              Do not tolerate any faults (default is to ignore most)");
  226.    info(handle, "-tolerant           Ignore all faults");
  227.    info(handle, "-mono               Select single audio channel output");
  228.    info(handle, "-stereo             Select dual audio channel output");
  229.    info(handle, "-verbose            Show text representation of song");
  230.    info(handle, "-repeats <count>    Number of repeats (0 is forever) (default 1)");
  231.    info(handle, "-speed <speed>      Song speed.  Some songs want 60 (default 50)");
  232.    info(handle, "-mix <percent>      Percent of channel mixing. (0 = spatial, 100 = mono)");
  233.    info(handle, "-new -old -both     Select default reading type (default is -both)");
  234.    info(handle, "-frequency <freq>   Set playback frequency in Hz");
  235.    info(handle, "-oversample <times> Set oversampling factor");
  236.    info(handle, "-transpose <n>      Transpose all notes up");
  237.    info(handle, "-scroll             Show what's going on");
  238.    info(handle, "-sync               Try to synch audio output with display");
  239. #ifdef VOLUME_CONTROL
  240.     info(handle, "-speaker                 Output audio to internal speaker");
  241.     info(handle, "-volume <n>         Set volume in dB");
  242. #endif
  243.    info(handle, "");
  244.    info(handle, "RunTime:");
  245.    info(handle, "e,x     exit program");
  246.    info(handle, "n       next song");
  247.    info(handle, "p       restart/previous song");
  248.    info(handle, ">       fast forward");
  249.    info(handle, "<       rewind");
  250.    info(handle, "S       NTSC tempo\t s\tPAL tempo");
  251.    end_info(handle);
  252.    }
  253.  
  254. /* Command-line options. */
  255. LOCAL struct long_option long_options[] =
  256. {
  257.    {"help",                0, 'H', OPT_HELP},
  258.    {"quiet",               0, 'Q', OPT_QUIET}, 
  259.    {"picky",               0, 'P', OPT_PICKY},
  260.    {"tolerant",            0, 'L', OPT_TOLERANT},
  261.    {"new",                 0, 'N', OPT_NEWONLY},
  262.    {"old",                 0, 'O', OPT_OLDONLY},
  263.    {"both",                0, 'B', OPT_BOTH},
  264.    {"mono",                0, 'M', OPT_MONO},
  265.    {"stereo",              0, 'S', OPT_STEREO},
  266.    {"verbose",             0, 'V', OPT_VERBOSE},
  267.    {"frequency",           1, 'f', OPT_FREQUENCY},
  268.    {"oversample",          1, 'o', OPT_OVERSAMPLE},
  269.    {"transpose",           1, 't', OPT_TRANSPOSE},
  270.    {"repeats",             1, 'r', OPT_REPEATS},
  271.    {"speed",               1, 's', OPT_SPEED},
  272.    {"mix",                 1, 'm', OPT_MIX},
  273.    {"start",               1, 'X', OPT_START},
  274.    {"cut",                 1, '-', OPT_CUT},
  275.    {"add",                 1, '+', OPT_ADD},
  276.    {"scroll",              0, 'v', OPT_SHOW},
  277.    {"sync",                0, '=', OPT_SYNC},
  278. #ifdef VOLUME_CONTROL
  279.     {"speaker",                    0, '#', OPT_SPEAKER},
  280.     {"volume",                    1, 'u', OPT_VOLUME},
  281. #endif
  282.    {0,                     0,  0 , 0}
  283. };
  284.  
  285.  
  286. /* global variable to catch various types of errors
  287.  * and achieve the desired flow of control
  288.  */
  289. int error;
  290.  
  291. LOCAL int optvalue(def)
  292. int def;
  293.    {
  294.    int d;
  295.  
  296.    if (sscanf(optarg, "%d", &d) == 1)
  297.       return d;
  298.    else
  299.       {
  300.       optind--;
  301.       return def;
  302.       }
  303.    }
  304.  
  305. LOCAL struct song *do_read_song(name, type)
  306. char *name;
  307. int type;
  308.    {
  309.    struct song *song;
  310.    struct exfile *file;
  311.  
  312.    file = open_file(name, "r", getenv("MODPATH"));
  313.    if (!file)
  314.       return NULL;
  315.    song = read_song(file, type); 
  316.    close_file(file);
  317.    return song;
  318.    }
  319.  
  320. LOCAL int ask_freq;
  321. LOCAL int oversample;
  322. LOCAL int stereo;
  323. LOCAL int start;
  324. LOCAL int transpose;
  325.  
  326.  
  327. LOCAL void parse_options(argc, argv)
  328. int argc;
  329. char *argv[];
  330.    {
  331.    int c;
  332.    
  333.    while ((c = getlongopt(argc, argv, long_options))
  334.       != BAD_OPTION)
  335.       switch(c)
  336.          {
  337.         case OPT_CUT:
  338.         case OPT_ADD:
  339.             {
  340.             int i;
  341.             unsigned long imask = 0;
  342.       
  343.             for (i = 0; optarg[i]; i++)
  344.                 {
  345.                 char c = tolower(optarg[i]);
  346.  
  347.                 if (c >= '1' && c <= '9')
  348.                     imask |= 1<< (c-'1');
  349.                 else if (c >= 'a' && c <= 'z')
  350.                     imask |= 1 << (c-'a'+9);
  351.                 }
  352.             if (c == OPT_ADD)
  353.                 set_pref_scalar(PREF_IMASK, imask);
  354.             else
  355.                 set_pref_scalar(PREF_IMASK, ~imask);
  356.             }        
  357.          break;
  358.       case OPT_OLDONLY:   /* old tracker type */
  359.          set_pref_scalar(PREF_TYPE, OLD);
  360.          break;
  361.       case OPT_NEWONLY:   /* new tracker type */
  362.          set_pref_scalar(PREF_TYPE, NEW);
  363.          break;
  364.       case OPT_SHOW:
  365.          set_pref_scalar(PREF_SHOW, TRUE);
  366.          break;
  367.       case OPT_SYNC:
  368.          set_pref_scalar(PREF_SYNC, TRUE);
  369.          break;
  370.       case OPT_BOTH:   /* both tracker types */
  371.          set_pref_scalar(PREF_TYPE, BOTH);
  372.          break;
  373.       case OPT_REPEATS:   /* number of repeats */
  374.          set_pref_scalar(PREF_REPEATS, optvalue(0));
  375.          break;
  376.       case OPT_SPEED:  
  377.          set_pref_scalar(PREF_SPEED, optvalue(50));
  378.          break;
  379.       case OPT_MONO:  
  380.          stereo = FALSE;
  381.          break;
  382.       case OPT_STEREO:  
  383.          stereo = TRUE;
  384.          break;
  385.       case OPT_OVERSAMPLE:  
  386.          oversample = optvalue(1);
  387.          break;
  388.       case OPT_FREQUENCY:
  389.          ask_freq = optvalue(0);
  390.          break;
  391.       case OPT_TRANSPOSE:
  392.          transpose = optvalue(0);
  393.          break;
  394.       case OPT_PICKY:
  395.          set_pref_scalar(PREF_TOLERATE, 0);
  396.          break;
  397.       case OPT_TOLERANT:
  398.          set_pref_scalar(PREF_TOLERATE, 0);
  399.          break;
  400.       case OPT_MIX:     /* % of channel mix. 
  401.                          * 0->full stereo, 100->mono */
  402.          set_mix(optvalue(30));
  403.          break;
  404.       case OPT_START:
  405.          start = optvalue(0);
  406.          break;
  407.       case OPT_HELP:
  408.          print_usage();
  409.          end_all(0);
  410.          /* NOTREACHED */
  411.       case OPT_VERBOSE:
  412.          set_pref_scalar(PREF_DUMP, TRUE);
  413.             break;
  414. #ifdef VOLUME_CONTROL
  415.         case OPT_VOLUME:
  416.             volume = optvalue(-20);
  417.             break;
  418.         case OPT_SPEAKER:
  419.             use_speaker = 1;
  420.             break;
  421. #endif
  422.          }
  423.    }
  424.  
  425. LOCAL struct song *load_song(name)
  426. char *name;
  427.    {
  428.    struct song *song;
  429.    char *buffer;
  430.    int i, j;
  431.    
  432.    i = strlen(name);
  433.    
  434.    for (j = i; j > 0; j--)
  435.       if (name[j] == '/' || name[j] == '\\')
  436.          {
  437.          j++;
  438.          break;
  439.          }
  440.    
  441.    buffer = malloc( i - j + 5);
  442.    if (buffer)
  443.       {
  444.       sprintf(buffer, "%s...", name + j);
  445.       status(buffer);
  446.       }
  447.  
  448.    
  449.    switch(get_pref_scalar(PREF_TYPE))
  450.       {
  451.    case BOTH:
  452.       song = do_read_song(name, NEW);
  453.       if (song)
  454.             break;
  455.       /* FALLTHRU */
  456.    case OLD:
  457.       song = do_read_song(name, OLD);
  458.       break;
  459.       /* this is explicitly flagged as a new module,
  460.        * so we don't need to look for a signature.
  461.        */
  462.    case NEW:
  463.       song = do_read_song(name, NEW_NO_CHECK);
  464.       break;
  465.       }
  466.    status(0);
  467.     return song;
  468.    }
  469.  
  470. int main(argc, argv)
  471. int argc;
  472. char **argv;
  473.    {
  474.    struct song *song;
  475.    boolean *is_song;
  476.    int i;
  477.  
  478.    struct tag *result;
  479.  
  480.    is_song = (boolean *)malloc(sizeof(boolean) * argc);
  481.    if (!is_song)
  482.       end_all("No memory left");
  483.  
  484.    for (i = 0; i < argc; i++)
  485.       is_song[i] = FALSE;        /* For termination */
  486.  
  487.    start = 0;
  488.    set_pref_scalar(PREF_IMASK, 0);
  489.    set_pref_scalar(PREF_BCDVOL, 0);
  490.    set_pref_scalar(PREF_DUMP, FALSE);
  491.    set_pref_scalar(PREF_SHOW, FALSE);
  492.    set_pref_scalar(PREF_SYNC, FALSE);
  493.    set_pref_scalar(PREF_TYPE, BOTH);
  494.    set_pref_scalar(PREF_REPEATS, 1);
  495.    set_pref_scalar(PREF_SPEED, 50);
  496.    set_pref_scalar(PREF_TOLERATE, 1);
  497.  
  498.    if (argc == 1)
  499.       {
  500.       print_usage();
  501.       end_all(0);
  502.       }
  503.  
  504.    ask_freq = read_env("FREQUENCY", 0);
  505.    oversample = read_env("OVERSAMPLE", 1);
  506.    transpose = read_env("TRANSPOSE", 0);
  507.    stereo = !getenv("MONO");
  508.    set_mix(30);
  509.  
  510.  
  511.  
  512.       /* check the command name for default reading type */
  513.  
  514.  
  515.    optind = 1;
  516.    for (optind = 1; optind < argc; optind++)
  517.       {
  518.       parse_options(argc, argv);
  519.       if (optind >= argc)
  520.          end_all(0);
  521.          
  522.    
  523.       song = load_song(argv[optind]);   
  524.       if (song)
  525.          is_song[optind] = TRUE;
  526.       else
  527.          {
  528.          puts("not a song");
  529.          is_song[optind] = FALSE;
  530.          continue;
  531.          }
  532. play_on:
  533.       if (get_pref_scalar(PREF_DUMP))
  534.          dump_song(song); 
  535.       transpose_song(song, transpose);
  536.       setup_audio(ask_freq, stereo, oversample);
  537.       result = play_song(song, start);
  538.       release_song(song);
  539.       status(0);
  540.       while (result = get_tag(result))
  541.          {
  542.          switch (result->type)
  543.             {
  544.          case PLAY_PREVIOUS_SONG:
  545.             optind--;
  546.             while ((optind > 0) && !is_song[optind])
  547.                optind--;
  548.             if (optind == 0)
  549.                end_all(0);
  550.             else
  551.                {
  552.                song = load_song(argv[optind]);
  553.                goto play_on;
  554.                }
  555.             /* NOTREACHED */
  556.          case PLAY_LOAD_SONG:
  557.             song = load_song(result->data.pointer);
  558.             free(result->data.pointer);
  559.             if (song)
  560.                goto play_on;
  561.          default:
  562.             break;
  563.             }
  564.          result++;
  565.          }
  566.             
  567.       }
  568.    end_all(0);
  569.    /* NOTREACHED */
  570.    }
  571.  
  572.  
  573.